home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / src.zoo / src / get_menus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-17  |  11.6 KB  |  426 lines

  1. /*                        Copyright (c) 1987 Bellcore
  2.  *                            All Rights Reserved
  3.  *       Permission is granted to copy or use this program, EXCEPT that it
  4.  *       may not be sold for profit, the copyright notice must be reproduced
  5.  *       on copies, and credit should be given to Bellcore where it is due.
  6.  *       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7.  */
  8. /*    $Header: get_menus.c,v 1.1 89/03/17 08:21:09 sau Exp $
  9.     $Source: /m1/mgr.new/src/RCS/get_menus.c,v $
  10. */
  11. static char    RCSid_[] = "$Source: /m1/mgr.new/src/RCS/get_menus.c,v $$Revision: 1.1 $";
  12.  
  13. /******************************************************************************
  14.  *
  15.  *    low level popup menu management routines
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "bitmap.h"
  20. #include "menu.h"
  21. #include "font.h"
  22.  
  23. #define MAX_LIST    100    /* max number of choices */
  24. #define BLIP        8    /* size of cursor blip */
  25.  
  26. #define BETWEEN(a,x,b)    (x)<(a)?a:((x)>(b)?b:x)
  27.  
  28. #define Pr_ropall(S,f)    bit_blit(S,0,0,BIT_WIDE(S),BIT_HIGH(S),f,NULL_DATA,0,0)
  29.  
  30. #define BAR(s,z)    bit_blit(s, 0, (z+1)*state->bar_sizey, \
  31.                                state->bar_sizex, state->bar_sizey, \
  32.                                BIT_NOT(BIT_DST), NULL_DATA, 0, 0);
  33.  
  34. #ifdef NOTRACK
  35. #define TRACKON(s,x,y)
  36. #define TRACKOFF(s,x,y)
  37. #else
  38. #define TRACKON(s,x,y) { \
  39.     bit_blit(&track,0,0,BLIP,BLIP, \
  40.     BIT_SRC,s,(x)-BLIP/2,(y)-BLIP/2); \
  41.     bit_blit(s,(x)-BLIP/2,(y)-BLIP/2,BLIP,BLIP, \
  42.     BIT_NOT(BIT_SRC) & BIT_DST,&mouse_bull,0,0); \
  43.     bit_blit(s,(x)-BLIP/2,(y)-BLIP/2,BLIP,BLIP, \
  44.     BIT_SRC | BIT_DST,&mouse_bull2,0,0); \
  45.     }
  46. #define TRACKOFF(s,x,y) \
  47.     bit_blit(s,(x)-BLIP/2,(y)-BLIP/2,BLIP,BLIP, \
  48.     BIT_SRC,&track,0,0)
  49. #endif
  50.  
  51. #ifndef Min
  52. #define Min(x,y)        ((x)>(y)?(y):(x))
  53. #endif
  54. #ifndef Max
  55. #define Max(x,y)        ((x)>(y)?(x):(y))
  56. #endif
  57. #define LIMIT(x,max)        (x)>(max)?1:(-(x)>(max)?-1:0)
  58. #define Abs(x)            ((x)>0?(x):-(x))
  59. #define MENU            struct menu_state
  60.  
  61. /*    The height of each selection area (i.e. word) in the pop-up menu.
  62.     The 2 extra pixels create a 1-pixel boarder above and below each word.
  63. */
  64. #define HIGH        (font->head.high+2)
  65.  
  66. extern BITMAP mouse_bull, mouse_bull2;
  67. static unsigned short save_bits[BLIP];
  68. static bit_static(track,BLIP,BLIP,save_bits,DEPTH);
  69.  
  70. /* allocate space for and initialize menu */
  71.  
  72. struct menu_state *
  73. menu_define(font,list,values,max,fg,bg)
  74. struct font *font;        /* which font to use for menu */
  75. char *list[];            /* list of menu items */
  76. char *values[];            /* list of return values */
  77. int max;            /* max number of menu items */
  78. int fg,bg;        /* clt values for menu color */
  79.    {
  80.    register int i, incr, count;    /* counters */
  81.    int size_x=0, size_y=0;
  82.    struct menu_state *state;    /* menu state */
  83.    char *malloc(), *save_line();
  84.    BITMAP *menu,            /* menu image */
  85.      *box,            /* menu pix_rect */
  86.      *inside,        /* box - border */
  87.      *save;            /* part of screen covered by menu */
  88.    int box_x, box_y;        /* dimensions of menu box */
  89.  
  90.    /* find size of box */
  91.  
  92.    for(count=0;list[count]!=(char *) 0 && count<(max>0?max:MAX_LIST); count++) {
  93.       size_x = Max(size_x,strlen(list[count]));
  94.       }
  95.  
  96.    /*    The 2 extra pixels are to allow a 1-pixel border to the left and right
  97.     of each word.
  98.    */
  99.    size_x = size_x * font->head.wide + 2;
  100.    size_y = count * HIGH;
  101.    box_x =size_x+2*MENU_BORDER;
  102.    box_y =size_y+2*MENU_BORDER;
  103.  
  104.    /* build box */
  105.  
  106.    menu = bit_alloc(box_x,box_y,NULL_DATA,DEPTH);
  107.    inside = bit_create(menu,MENU_BORDER,MENU_BORDER,size_x,size_y);
  108.  
  109.    /* paint text into box */
  110.  
  111. #ifdef COLOR
  112.    Pr_ropall(menu,BIT_SRC|GETCOLOR(fg));
  113.    Pr_ropall(inside,BIT_SRC|GETCOLOR(bg));
  114. #else
  115.    Pr_ropall(menu,BIT_SET);
  116.    Pr_ropall(inside,BIT_CLR);
  117. #endif
  118.    for(i=0,incr=HIGH-1;i<count;i++,incr+=HIGH) {
  119. #ifdef COLOR
  120.       /* do local color here */
  121.       put_str(inside,1,incr,font,
  122.               BIT_SRC^BIT_DST | GETCOLOR(bg)^GETCOLOR(fg),list[i]);
  123. #else
  124.       put_str(inside,1,incr,font,BIT_SRC,list[i]);
  125. #endif
  126.       }
  127.  
  128.    /* save the menu state */
  129.  
  130.    if ((state = (MENU *) malloc(sizeof(struct menu_state))) == (MENU *) 0) {
  131.       bit_destroy(inside);
  132.       bit_destroy(menu);
  133.       return(state);
  134.       }
  135.  
  136.    /* get the values */
  137.  
  138.    if (values != (char **) 0) {
  139.       state -> action = (struct menu_action *) 
  140.                malloc(count * sizeof(struct menu_action));
  141.       if (state->action) for(i=0;i<count;i++) {
  142.          state->action[i].value = save_line(values[i]);
  143.          state->action[i].next_menu = -1;
  144.          }
  145.       
  146.       }
  147.    else
  148.       state->action = (struct menu_action *) 0;
  149.  
  150.    state -> menu = menu;
  151.    state -> bar_sizex = size_x;
  152.    state -> bar_sizey = HIGH;
  153.    state -> count = count;
  154.    state -> current = 0;
  155.    state -> next = -1;
  156.    state->flags = 0;
  157.    state -> screen = (BITMAP *) 0;
  158.    state -> save = (BITMAP *) 0;
  159.  
  160.    bit_destroy(inside);
  161.    return(state);
  162.    }
  163.  
  164. /* put the menu on the display */
  165.  
  166. struct menu_state *
  167. menu_setup(state,screen,x,y,start)
  168. struct menu_state *state;    /* existing menu state */
  169. BITMAP *screen;            /* where to put the menu */
  170. int x,y;            /* current offset of mouse on screen */
  171. int start;            /* preselected item */
  172.    {
  173.    register int i, incr, count;    /* counters */
  174.    char *malloc();
  175.  
  176.    /* position the box on the screen */
  177.  
  178.    if (state->BIT_WIDE(menu)>BIT_WIDE(screen) ||
  179.        state->BIT_WIDE(menu)>BIT_WIDE(screen) ||
  180.        state->save)
  181.        return((MENU *) 0);
  182.  
  183.    x = Min(x,BIT_WIDE(screen) - state->BIT_WIDE(menu));
  184.    y = Min(y,BIT_HIGH(screen) - 
  185.                  state->BIT_HIGH(menu) - state->bar_sizey);
  186.    y = Max(y,state->bar_sizey+BLIP);
  187.  
  188.    state->save = bit_alloc(state->BIT_WIDE(menu),state->BIT_HIGH(menu),
  189.                   NULL_DATA,DEPTH);
  190.    bit_blit(state->save,0,0,state->BIT_WIDE(menu),
  191.           state->BIT_HIGH(menu),BIT_SRC,screen,x,y);
  192.  
  193.    /* initialize the menu */
  194.  
  195.    state -> screen = screen;
  196.    state -> current = start;
  197.    state -> menu_startx = x;
  198.    state -> menu_starty = y;
  199.    state -> x_pos = state-> bar_sizex/2;
  200.  
  201.    bit_blit(screen,x,y,state->BIT_WIDE(menu),state->BIT_HIGH(menu),BIT_SRC,
  202.           state->menu,0,0);
  203.  
  204.    if (start>=0 && start<state->count) {
  205.        BITMAP *inside = bit_create(screen,state->menu_startx+MENU_BORDER,
  206.                     state->menu_starty+MENU_BORDER,
  207.                     state->bar_sizex,state->bar_sizey*state->count);
  208.        BAR(inside,start-1);
  209.        bit_destroy(inside);
  210.        }
  211.    
  212.    return(state);
  213.    }
  214.  
  215.  
  216. /******************************************************************************
  217.  
  218. allow user to select an item 
  219.  
  220.  */
  221.  
  222. int menu_get(state,mouse,button,exit)
  223. struct menu_state *state;
  224. int mouse;            /* fd to read mouse data from */
  225. int button;            /* button termination condition (not yet)*/
  226. int exit;            /* off-menu exit codes */
  227.    {
  228.    register BITMAP *inside;    /* the menu */
  229.    register int y_position;
  230.    register int x_position;
  231.    int push;
  232.    int x_mouse, y_mouse;    /* mouse delta's */
  233.    int done=0;
  234.    int inverse;            /* selected item */
  235.    int count;            /* number of items */
  236.    int old;
  237.  
  238.    if (state == (MENU *) 0)
  239.        return(-1);
  240.  
  241.    old = inverse = state -> current;
  242.    count = state -> count;
  243.    state->exit=0;
  244.  
  245.    /* set up text region */
  246.  
  247.    inside = bit_create(state->screen,state->menu_startx+MENU_BORDER,
  248.                     state->menu_starty+MENU_BORDER - state->bar_sizey,
  249.                     state->bar_sizex,state->bar_sizey*(count+2));
  250.  
  251.    /* make sure we aren't already exited */
  252.  
  253.    if (exit&EXIT_BOTTOM && inverse >= count) {
  254.       old = inverse = count-1;
  255.       BAR(inside,inverse);    /* on */
  256.       }
  257.  
  258.    /* set initial blip position */
  259.  
  260.    x_position = state->x_pos;
  261.    y_position = state->bar_sizey*(inverse+1) + state->bar_sizey/2;
  262.  
  263.    /* track the mouse */
  264.  
  265.    TRACKON(inside,x_position,y_position);        /* on */
  266.    do {
  267.       push = mouse_get(mouse,&x_mouse,&y_mouse);
  268.       TRACKOFF(inside,x_position,y_position);        /* off */
  269.       x_position += x_mouse;
  270.       y_position -= y_mouse;
  271.       y_position = BETWEEN(BLIP, y_position, (2+count)*state->bar_sizey-BLIP);
  272.  
  273.       if (x_position <= 0 && (exit&EXIT_LEFT)) {
  274.          state->exit = EXIT_LEFT;
  275.          done++;
  276.          }
  277.       else if (x_position >= BIT_WIDE(inside) && (exit&EXIT_RIGHT)) {
  278.          state->exit = EXIT_RIGHT;
  279.          done++;
  280.          }
  281.  
  282.       x_position = BETWEEN(BLIP/2, x_position, BIT_WIDE(inside) - BLIP/2);
  283.  
  284.       TRACKON(inside,x_position,y_position);        /* on */
  285.  
  286.       if (done)
  287.          break;
  288.  
  289.       /* fix bar */
  290.  
  291.       inverse = (2+count) * y_position / BIT_HIGH(inside) - 1;
  292.       if (inverse != old) {
  293.          TRACKOFF(inside,x_position,y_position);        /* off */
  294.          if (old >=0 && old < count)
  295.             BAR(inside,old);        /* off */
  296.          if (inverse >=0 && inverse < count)
  297.             BAR(inside,inverse);    /* on */
  298.          old = inverse;
  299.  
  300.          if (inverse < 0 && exit&EXIT_TOP) {
  301.             state->exit = EXIT_TOP;
  302.             done++;
  303.             }
  304.          else if (inverse >= count && exit&EXIT_BOTTOM) {
  305.             state->exit = EXIT_BOTTOM;
  306.             done++;
  307.             }
  308.          TRACKON(inside,x_position,y_position);        /* on */
  309.          }
  310.       }
  311.       while (push != button && !done);
  312.    state->current = inverse;
  313.    state->x_pos = x_position;
  314.    TRACKOFF(inside,x_position,y_position);        /* off */
  315.    bit_destroy(inside);
  316.    return(0);
  317.    }
  318.  
  319. /******************************************************************************
  320.  
  321. remove the menu drom the screen, restore previous screen contents
  322.  
  323.  */
  324.  
  325. struct menu_state *
  326. menu_remove(state)
  327. struct menu_state *state;
  328.    {
  329.    if (state == (MENU *) 0) return(state);
  330.    if (state->save != (BITMAP *) 0) {
  331.       bit_blit(state->screen,state->menu_startx,state->menu_starty,
  332.          state->BIT_WIDE(save),state->BIT_HIGH(save),BIT_SRC,state->save,0,0);
  333.       bit_destroy(state->save);
  334.       state->save = (BITMAP *) 0;
  335.       }
  336.    return(state);
  337.    }
  338.  
  339. /* free space associated with a menu */
  340.  
  341. int
  342. menu_destroy(state)
  343. struct menu_state *state;
  344.    {
  345.    register int i;
  346.  
  347.    menu_remove(state);
  348.  
  349.    if (state->menu != (BITMAP *)0)
  350.       bit_destroy(state->menu);
  351.  
  352.    if (state->action != (struct menu_action *) 0) {
  353.       for(i=0;i<state->count;i++)
  354.          if (state->action[i].value)
  355.             free(state->action[i].value);
  356.       free(state->action);
  357.       }
  358.  
  359.    free(state);
  360.    return(0);
  361.    }
  362.  
  363. /* put a character string into a bitmap - only used for menus */
  364.  
  365. int
  366. put_str(map,x,y,font,op,str)
  367. BITMAP *map;
  368. register int x;
  369. int y;
  370. struct font *font;
  371. int op;
  372. register char *str;
  373.    {
  374.    register char c;
  375.    register int wide = font->head.wide;
  376.    register int high = font->head.high;
  377.  
  378.    while (c = *str++) {
  379.       bit_blit(map,x,y-high,wide,high,op,font->glyph[c],0,0);
  380.       x+=wide;
  381.       }
  382.    }
  383.  
  384. /* copy a menu  - for environment stacks */
  385.  
  386. struct menu_state *
  387. menu_copy(menu)
  388. register struct menu_state *menu;
  389.    {
  390.    register struct menu_state *tmp;
  391.    register int i;
  392.    char *alloc(), *malloc(), *save_line();
  393.  
  394.    if (menu == (struct menu_state *) 0)
  395.       return(menu);
  396.  
  397.    if ((tmp = (struct menu_state *) malloc(sizeof(struct menu_state))) 
  398.                                                    == (struct menu_state *) 0)
  399.       return((struct menu_state *) 0);
  400.  
  401.    bcopy((char *) menu,(char *)tmp,sizeof(struct menu_state));
  402.  
  403.    /* copy menu image */
  404.  
  405.    if (menu->menu) {
  406.       tmp->menu = bit_alloc(BIT_WIDE(menu->menu),
  407.                             BIT_HIGH(menu->menu),NULL_DATA,DEPTH);
  408.       bit_blit(tmp->menu,0,0,BIT_WIDE(tmp->menu),BIT_HIGH(tmp->menu),
  409.                             BIT_SRC,menu->menu,0,0);
  410.       }
  411.  
  412.    /* copy menu values */
  413.  
  414.    if (menu->action != (struct menu_action *) 0) {
  415.       tmp->action = (struct menu_action *) 
  416.                     malloc(sizeof(struct menu_action)*menu->count);
  417.       if (tmp->action)
  418.          for(i=0;i<menu->count;i++) {
  419.             tmp->action[i].value = save_line(menu->action[i].value);
  420.             tmp->action[i].next_menu = menu->action[i].next_menu;
  421.             } 
  422.       }
  423.  
  424.    return(tmp);
  425.    }
  426.